package com.cwolf.qr.activity;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;

import android.Manifest;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.Shader;
import android.hardware.Camera;
import android.hardware.camera2.CameraManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.provider.MediaStore;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import com.google.zxing.BinaryBitmap;
import com.google.zxing.LuminanceSource;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.NotFoundException;
import com.google.zxing.PlanarYUVLuminanceSource;
import com.google.zxing.RGBLuminanceSource;
import com.google.zxing.Result;
import com.google.zxing.common.HybridBinarizer;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

public class QrScanerActivity extends AppCompatActivity implements QrDecodeListener {

    //当前页面所需要的权限.相机、相册读取
    //定义权限请求CODE
    public final int cameraPermissionCode = 1;
    public final int readStorageCode = 2;
    //相机是否已授权
    boolean cameraPermissionIsOk ;

//    CameraManager cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);版本21以上
    //相机
    Camera camera;
    //图像渲染显示器
    SurfaceView surfaceView;
    //覆盖上去的view
    SurfaceView coverView;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_qr_scaner);
        surfaceView = findViewById(R.id.surfaceView);
        coverView = findViewById(R.id.coverView);
        //进入页面直接请求相机权限
        cameraPermissionIsOk = requestPermission(Manifest.permission.CAMERA,cameraPermissionCode);
        //初始化 surface view.绑定相关事件
        initSurfaceView();
        initCoverSurfaceView();

        Button button = findViewById(R.id.btnPic);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                boolean re = requestPermission(Manifest.permission.READ_EXTERNAL_STORAGE, readStorageCode);
                if(re){
                    //打开相册读取照片
                    openPictures();
                }
            }
        });

    }

    private void openPictures() {

        Intent intent = new Intent(Intent.ACTION_PICK, null);
        intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
        startActivityForResult(intent, readStorageCode);

    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if(requestCode==readStorageCode){//相册返回
            if(data!=null){
                final Uri uri = data.getData();
                Runnable runner = new Runnable() {
                    @Override
                    public void run() {
                        Bitmap bitmap = null;
                        try {
                            bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri));
                        } catch (FileNotFoundException e) {
                            e.printStackTrace();
                        }
                        final Result result = decodeQr(bitmap);
                        QrScanerActivity.this.runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                if (result == null) {
                                    initSurfaceView();
                                    Toast.makeText(QrScanerActivity.this, "解码失败", Toast.LENGTH_LONG).show();
                                    initSurfaceView();
                                    initCoverSurfaceView();
                                    startPreview();
                                    initFinderView();
                                } else {
                                    QrScanerActivity.this.decodeSuccess(result);
                                    return;
                                }
                            }
                        });


                    }
                };
                new Thread(runner).start();


            }else{
                initSurfaceView();
            }


        }

    }

    /**
     * camera 开始渲染到 surface view
     */
    void startPreview() {
        try {
            boolean isOpen = openCamera();
            if (isOpen) {
                camera.setPreviewDisplay(surfaceView.getHolder());
                camera.setDisplayOrientation(90);//摄像头画面默认是横屏，所以需要选装90度，后面解码还会遇到相关问题
                camera.setPreviewCallback(new QrPreviewCallBack(this));
                camera.startPreview();//开始预览
                camera.autoFocus(new QrFocusCallBack());
            }
        }catch (Exception e){
            Log.e("preview","开始渲染异常",e);
        }

    }

    /**
     * 初始化覆盖的view
     */
    void initCoverSurfaceView(){
        SurfaceHolder holder = coverView.getHolder();
        coverView.setZOrderMediaOverlay (true);
        holder.setFormat(PixelFormat.TRANSPARENT);
        holder.addCallback(new SurfaceHolder.Callback() {
            @Override
            public void surfaceCreated(SurfaceHolder holder) {

            }

            @Override
            public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
                initFinderView();//取景框,如果进来就有权限，那么将在这里初始化
                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        Canvas canvas = coverView.getHolder().lockCanvas();
                        canvas.drawARGB(100,0,0,0);
                        canvas.save();
                        coverView.getHolder().unlockCanvasAndPost(canvas);
                    }
                },50);
            }

            @Override
            public void surfaceDestroyed(SurfaceHolder holder) {

            }
        });

    }

    Rect finderRect;
    Rect getFinderViewRect(){
        if(finderRect!=null){
            return finderRect;
        }

        //计算出rect
        int width = coverView.getWidth();
        int height = coverView.getHeight();

        int viewWidth = (int) (width * 0.7);
        if (viewWidth > 800) {
            viewWidth = 800;
        } else if (viewWidth < 300) {
            viewWidth = 300;
        }
        int qrHeight = viewWidth;
        int left = (width - viewWidth) / 2;
        int top = (height - qrHeight) / 2;
        //屏幕上显示区域
        finderRect =  new Rect(left, top, viewWidth + left, qrHeight + top);
        return finderRect;

    }

    int lineY = 0;
    /**
     * 初始化取景框
     */
    void initFinderView(){
        Rect rect = getFinderViewRect();
        //画个取景框
        Rect finderViewRect = new Rect(rect.left,rect.top,rect.right,rect.bottom);
        SurfaceHolder holder = coverView.getHolder();
        Canvas canvas = holder.lockCanvas(finderViewRect);
        canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
        int perH =(rect.bottom-rect.top)/60;
        if(lineY>rect.bottom-perH){
            lineY = 0;
        }
        //画一条扫描线
        if(lineY==0) {//第一次画线
            lineY = rect.top+perH;
        }
            final Paint linePaint = new Paint();
            linePaint.setColor(Color.GREEN);
            linePaint.setStrokeWidth(6);
            linePaint.setAlpha(150);
            //渐变线，也可以直接画个普通线
            Shader mShader = new LinearGradient(rect.left,0,rect.right,0,new int[] {Color.rgb(173,245,191),Color.GREEN,Color.rgb(173,245,191)},null,Shader.TileMode.REPEAT);

            linePaint.setShader(mShader);
            canvas.drawLine(rect.left+10,lineY,rect.right-10,lineY,linePaint);


        holder.unlockCanvasAndPost(canvas);
        //1.5 秒扫描一次，50*30 = 1500 ms
        lineY+=perH;

        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                if(camera!=null){
                    initFinderView();
                }

            }
        },30);
    }




    /**
     * 初始化 渲染显示
     * 在摄像头开启后才进行这些设置操作
     */
    void initSurfaceView()  {

        SurfaceHolder holder = surfaceView.getHolder();
        holder.addCallback(new SurfaceHolder.Callback() {
            @Override
            public void surfaceCreated(SurfaceHolder holder) {

            }
            @Override
            public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
                    startPreview();
            }

            @Override
            public void surfaceDestroyed(SurfaceHolder holder) {
                    stopPreview(this);

            }
        });



    }


    /**
     * 打开摄像头
     * @return
     */
    public boolean openCamera() {

        if(camera!=null){
            return true;
        }
        if(!cameraPermissionIsOk){
            return false;
        }

        camera = Camera.open();//打开默认摄像头
        if(camera==null){
            Toast.makeText(QrScanerActivity.this,"摄像头打开失败！",Toast.LENGTH_LONG);
            return false;
        }
        return true;
    }


    /**
     * 请求获取权限
     * @param permission
     */
    boolean requestPermission(String permission,int requestCode){

            int checkResult = ActivityCompat.checkSelfPermission(QrScanerActivity.this, permission);
            if(checkResult!= PackageManager.PERMISSION_GRANTED){//未授权
                //请求权限
                ActivityCompat.requestPermissions(QrScanerActivity.this,new String[]{permission},requestCode);

                return false;
            }return true;


    }

    /**
     * 权限回调
     * @param requestCode
     * @param permissions
     * @param grantResults
     */
    @RequiresApi(api = Build.VERSION_CODES.P)
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
            switch (requestCode){
                case cameraPermissionCode:
                    if(grantResults[0]==PackageManager.PERMISSION_GRANTED){//获取权限成功
                        cameraPermissionIsOk = true;
                        startPreview();

                    }else{
                        Toast.makeText(QrScanerActivity.this,"扫一扫功能需要摄像头拍摄，不授权将无法使用！",Toast.LENGTH_LONG).show();
                        //3秒后重新申请权限
                        new Handler().postDelayed(new Runnable() {
                            @Override
                            public void run() {
                                requestPermission(Manifest.permission.CAMERA,cameraPermissionCode);
                            }
                        },3000);
                    }


                    break;
                case readStorageCode:
                    openPictures();
                    break;

            }
    }

    /**
     * 停止渲染
     */
    void stopPreview(SurfaceHolder.Callback callback){
        if(callback!=null){
            surfaceView.getHolder().removeCallback(callback);
        }
        if(camera!=null){

            try {
            camera.setPreviewCallback(null);
            camera.stopPreview();
            camera.release();
            camera = null;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }


    }


    @Override
    public void decodeSuccess(final Result result) {
        try {
            Toast.makeText(QrScanerActivity.this,"解码结果："+result.getText(),Toast.LENGTH_LONG).show();
            stopPreview(null);
        }catch (Exception e)
        {
            e.printStackTrace();
        }

//
    }
    /**
     * 识别二维码
     * @param bmp
     * @return
     */
    public static Result decodeQr(Bitmap bmp) {
        bmp = getSmallerBitmap(bmp);
        Result rawResult = null;
        int width = bmp.getWidth();
        int height = bmp.getHeight();
        int[] pixels = new int[width * height];
        bmp.getPixels(pixels, 0, width, 0, 0, width, height);
        LuminanceSource source = new RGBLuminanceSource(width, height, pixels);
        if (source != null) {
            BinaryBitmap binaryBitmap = new BinaryBitmap(new HybridBinarizer(source));
            try {
                rawResult = new MultiFormatReader().decode(binaryBitmap);
            } catch (NotFoundException e) {
                e.printStackTrace();
            }
        }
        return rawResult;
    }

    /**
     * 有时大图解析不了，从网上复制来的代码
     * @param bitmap
     * @return
     */
    public static Bitmap getSmallerBitmap(Bitmap bitmap){
        int size = bitmap.getWidth()*bitmap.getHeight() / 200000;
        if (size <= 1) return bitmap; // 如果小于
        else {
            Matrix matrix = new Matrix();
            matrix.postScale((float) (1 / Math.sqrt(size)), (float) (1 / Math.sqrt(size)));
            Bitmap resizeBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
            return resizeBitmap;
        }
    }
}
